package LeetCode.String;

/**
 * # 1. 字符串循环移位包含
 * [编程之美 3.1](#)
 * s1 = AABCD, s2 = CDAA
 * Return : true
 * 给定两个字符串 s1 和 s2，要求判定 s2 是否能够被 s1 做循环移位得到的字符串包含。
 * <p>
 * 比如："abcdefgh"循环右移两位就是"ghabcdef"
 * <p>
 * 思路：
 * s1 进行循环移位的结果是 s1s1 的子字符串，因此只要判断 s2 是否是 s1s1 的子字符串即可。
 * <p>
 * https://blog.csdn.net/jingsuwen1/article/details/51931464
 *
 *
 *
 * 描述 https://ask.csdn.net/questions/1053041
 * 对于一个字符串来说，定义一次循环移位操作为：将字符串的第一个字符移动到末尾形成新的字符串。
 * 给定两个字符串s1和s2，要求判定其中一个字符串是否是另一字符串通过若干次循环移位后的新字符串的子串。例如CDAA是由AABCD两次移位后产生的新串BCDAA的子串，而ABCD与ACBD则不能通过多次移位来得到其中一个字符串是新串的子串。
 * 输入一行，包含两个字符串，中间由单个空格隔开。字符串只包含字母和数字，长度不超过30。
 * 输出
 * 如果一个字符串是另一字符串通过若干次循环移位产生的新串的子串，则输出true，否则输出false。
 * 样例输入
 * AABCD CDAA
 * 样例输出
 * true
 */
public class Test1 {

    //法一：使用一个辅助字符串s = s1+s1;
    //String转StringBuilder ：StringBuilder sb = new StringBuilder(str1);
    private static boolean moveInclude(String str1, String str2) {
        if (str1 == null || str2 == null || str1.length() < str2.length())
            return false;
        StringBuilder sb = new StringBuilder(str1);
        sb.append(str1);
        return sb.toString().contains(str2);
    }

    //法二：循环匹配s1和s2的字符，当s1达到末尾时，返回s1首部，继续匹配。
    private static boolean moveInclude2(String str1, String str2) {
        if (str1 == null || str2 == null || str1.length() < str2.length())
            return false;
        for (int i = 0; i < str1.length(); i++)//以s1的每个字符都作为匹配首部进行循环匹配
        {
            int j = 0;
            for (; j < str2.length(); j++) {
                if (str2.charAt(j) != str1.charAt((i + j) % str1.length()))
                    break;
            }
            if (j == str2.length())
                return true;
        }
        return false;
    }


    public static void main(String[] args) {

        String str1 = "AABCD";
        String str2 = "CDAA";
        System.out.println("字符串 1. 字符串循环移位包含 "+str1+" "+str2);
        System.out.println("法一 "+moveInclude(str1, str2));
        System.out.println("法二 "+moveInclude2(str1, str2));
    }
}
